﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NDimArrayNamespace;
using ParserCore;
using QLabValues;

namespace Memory_Access
{
    public class VarTable: AbstractTable, ICloneable
    {
        public VarTable()
        {
            _table = new Dictionary<Identifier, IQLabValue>();
        }

        public IQLabValue LookUp(Identifier ID)
        {
            IQLabValue value;
            bool success = _table.TryGetValue(ID, out value);
            if (!success) return null;
            else return value;
        }

        public void AddVariable(Identifier ID, IQLabValue value)
        {
            if (_table.Keys.Contains(ID))
                _table[ID] = value;
            else
                _table.Add(ID, value);
        }

        /// <summary>
        /// Performs a change such as a(1,1) = 3.<br/>
        /// Takes out the array from the table, calculates the change that needs to be made & performs it.
        /// </summary>
        /// <param name="callExpression"></param>
        /// <param name="value"></param>
        /// 
        // TODO: [Andrija] [kad se razvrsta hijerarhija klasa za nizove/matrice...]
        public void ChangeArrayVariable(Identifier name, int[] coordinates, IQLabValue value)
        {
            /*IQLabValue arrayValue = this.LookUp(name);
            Type tArray = typeof(NDimArray<>);
            Type tElement = value.GetType();
            Type finalType = tArray.MakeGenericType(tElement);

            if (arrayValue.GetType().Equals(finalType)) // TODO: check if it works :)
            {
                // TODO: reflection reflection reflection :-/
                // TODO: [syntax] ((NDimArray<>)arrayValue)[coordinates] = value;
                //var finalArray = finalType.AssemblyQualifiedName;
            }*/
        }

        /*
         * U this.table upisuje vrednosti promenljivih iz table koje nisu argumetni i nisu u povratne vrednosti
         * */
        public void MergeVariables(VarTable table, Identifier[] arguments, Identifier[] returnList)
        {
            // if variable's identifier is not some of arguments or in return list, update current table
            foreach (Identifier ID in table._table.Keys)
                if (!arguments.Contains(ID) && !returnList.Contains(ID))
                    this.AddVariable(ID, table._table[ID]);
        }

        private Dictionary<Identifier, IQLabValue> _table;
        public Dictionary<Identifier, IQLabValue> Table
        {
            get
            {
                return _table;
            }
        }

        public object Clone()
        {
            return this.MemberwiseClone();      // call clone method
        }

        public void RemoveVariable(Identifier ID)
        {
            _table.Remove(ID);
        }
    }
}
